﻿using System;
using System.Collections;
using System.Collections.Generic;
using AudioStudio;
using LogSystem;
using RootMotion.FinalIK;
using UnityEngine;
using WorldMapBase.Layer;
using Yoozoo.Core.Common;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Gameplay.Liberty.World;
using Yoozoo.Mars.Got;

namespace Yoozoo.Gameplay.Liberty.AI
{
    [RequireComponent(typeof(AnimationAgent))]
    public class IKAgent : MonoBehaviour
    {
        /// <summary>
        /// 质量手枪瞄准IK角度限制
        /// </summary>
        private static readonly Dictionary<QualityEnum, KeyValuePair<int, int>> _QualityHandGunAimIKLimits =
            new Dictionary<QualityEnum, KeyValuePair<int, int>>
            {
                { QualityEnum.Low , new KeyValuePair<int, int>(10,15)},
                { QualityEnum.Medium , new KeyValuePair<int, int>(10,15)},
                { QualityEnum.High , new KeyValuePair<int, int>(-10,15)},
                { QualityEnum.VeryHigh , new KeyValuePair<int, int>(-10,15)},
                { QualityEnum.Perfect , new KeyValuePair<int, int>(-10,15)},
            };
        public Dictionary<QualityEnum, KeyValuePair<int, int>> QualityHandGunAimIKLimits => _QualityHandGunAimIKLimits;

        /// <summary>
        /// 质量手枪瞄准IK支持
        /// </summary>
        private static readonly Dictionary<QualityEnum, bool> _QualityIKSupport = 
            new Dictionary<QualityEnum, bool>
            {
                { QualityEnum.Low, false },
                { QualityEnum.Medium, false },
                { QualityEnum.High, true },
                { QualityEnum.VeryHigh, true },
                { QualityEnum.Perfect, true },
            };

        // 淡入淡出类型
        enum FadeType
        {
            // 没有
            None = 0,
            // 淡入
            FadeIn,
            // 淡出
            FadeOut,
        }

        // LookAt类型 (注意！！根据权重排序，后面的枚举优先)
        public enum LookAtType
        {
            // 没有
            None = 0,
            // 看向玩家
            LookAtPlayer,
            // 瞄准
            Aim,
        }
        // LookAt类型对应的HeadWeight查询表        
        private static readonly Dictionary<LookAtType, float> _LookAtHeadWeightLimits = new Dictionary<LookAtType, float>
        {
            { LookAtType.None, 0 },
            { LookAtType.LookAtPlayer, 1f },
            { LookAtType.Aim, 0.6f },
        };

        private AIEntity _aiEntity;
        private AIData _aiData;
        private Transform _transform;
        
#region LookAtIK参数
        [Header("LookAtIK参数")]
        // 淡入时长
        [SerializeField]
        private float _lookAtFadeInDuration = 0.4f;
        // 淡出时长
        [SerializeField]
        private float _lookAtFadeOutDuration = 0.3f;
        // 淡入淡出计时器
        private float _lookAtFadeTimer = 0;  
        // 当前淡入淡出的状态
        private FadeType _lookAtFadeType = FadeType.None;
        
        // LookAtIK
        [SerializeField]
        private LookAtIK _lookAtIK;
        // 当前LookAt类型
        [SerializeField]
        private LookAtType _lookAtType = LookAtType.None;
        // 当前LookAt类型限制的HeadWeight
        [SerializeField]
        private float _lookAtHeadWeightLimit = 0;
        // 该npc是否支持空闲时看向玩家
        [SerializeField]
        private bool _supportLookAtPlayer = false;
        [Tooltip("lookAt检测半径的平方")]
        private float _lookAtSqrRadius = 64f;
        [Tooltip("lookAt检测角度")]
        private float _lookAtAngle = 120f;
        // LookAtIK是否开启
        [SerializeField]
        private bool _lookAtEnabled;
#endregion
        
#region 手枪瞄准IK参数
        [Header("手枪瞄准IK参数")]
        // 淡入时长
        [SerializeField]
        private float _handGunFadeInDuration = 0.15f;
        // 淡出时长
        [SerializeField]
        private float _handGunFadeOutDuration = 0.15f;
        // 淡入淡出计时器
        private float _handGunFadeTimer = 0;  
        // 当前淡入淡出的状态
        private FadeType _handGunFadeType = FadeType.None;

        // 手枪瞄准IK
        [SerializeField]
        private AimIK _handGunAimIK;
        // 手枪瞄准PoleTarget高度
        [SerializeField]
        private float _handGunPoleTargetHeight = 3f;
        // 手枪瞄准距离限制 (超过距离才更新)
        [SerializeField] 
        private float _handGunAimIKLimitRange = 2f;
        // 手枪瞄准PoleTarget
        [SerializeField]
        private Transform _handGunPoleTarget;
        // 手枪瞄准IK更新回调
        private Action _afterHandGunIKUpdate;
        // 手枪瞄准IK是否开启
        [SerializeField]
        private bool _handGunEnabled;
#endregion

        void Awake()
        {
            _transform = transform;
            
            Animator animator = gameObject.GetComponent<Animator>();
            // LookAtIK
            Transform headBone = animator.GetBoneTransform(HumanBodyBones.Head);
            if (headBone != null)
            {
                if (_lookAtIK == null)
                {
                    _lookAtIK = gameObject.GetOrAddComponent<LookAtIK>();
                }
                _lookAtIK.solver.headWeight = 1f;
                _lookAtIK.solver.target = null;
                _lookAtIK.solver.head.transform = headBone;
                _lookAtIK.solver.IKPositionWeight = 0;
                // 禁用组件，自己手动更新
                _lookAtIK.enabled = false;
                // 关闭LookAtIK更新
                SetLookAtEnabled(false);
            }
            
            // 手枪瞄准IK
            if (!_handGunAimIK)
            {
                _handGunAimIK = gameObject.GetComponent<AimIK>();
            }
            if (_handGunAimIK)
            {
                if (!_handGunPoleTarget)
                {
                    GameObject poleTarget = new GameObject("HandGunPoleTarget");
                    _handGunPoleTarget = poleTarget.transform;
                    _handGunPoleTarget.SetParent(transform);
                    _handGunPoleTarget.localPosition = Vector3.up * _handGunPoleTargetHeight;
                }
                
                // 设置PoleTarget
                SetHandGunPoleTarget(_handGunPoleTarget);
                // 禁用组件，自己手动更新
                _handGunAimIK.enabled = false;
                // 关闭AimIK更新
                _handGunEnabled = false;
            }
        }

        void Start()
        {
            // 手动初始化IK （Prefab里disable的IK组件，没有办法走Start的初始化，这里手动调用一下）
            // LookAtIK
            if (_lookAtIK)
            {
                _lookAtIK.Initiate();
            }
            // 手枪瞄准IK
            if (_handGunAimIK)
            {
                _handGunAimIK.Initiate();
            }
        }
        
        public void InitData(AIEntity aiEntity)
        {
            _aiEntity = aiEntity;
            _aiData = aiEntity.data;
        }
        
#region LookAtIK

        /// <summary>
        /// 设置是否开启LookAtIK更新
        /// </summary>
        /// <param name="enabled"></param>
        public void SetLookAtEnabled(bool enabled)
        {
            if (!_lookAtIK)
            {
                return;
            }
            
            _lookAtEnabled = enabled;
            // _lookAtEnabled = false; // TODO: 临时关闭LookAtIK
        }
        
        /// <summary>
        /// LookAtIK淡入
        /// </summary>
        public void LookAtIKFadeIn()
        {
            if (!_lookAtIK)
            {
                return;
            }
            
            SetLookAtEnabled(true);
            _lookAtFadeType = FadeType.FadeIn;
            float weight = _lookAtIK.solver.IKPositionWeight;
            weight = weight > 1 ? 1 : weight;
            if (weight > 0)
            {
                _lookAtFadeTimer = _lookAtFadeInDuration * weight; // 从当前weight处淡入
            }
            else
            {
                _lookAtFadeTimer = 0;
            }
        }
        
        /// <summary>
        /// LookAtIK淡出
        /// </summary>
        public void LookAtIKFadeOut()
        {
            if (!_lookAtIK)
            {
                return;
            }

            float weight = _lookAtIK.solver.IKPositionWeight;
            weight = weight > 1 ? 1 : weight;
            if (weight > 0)
            {
                SetLookAtEnabled(true);
                _lookAtFadeType = FadeType.FadeOut;
                _lookAtFadeTimer = _lookAtFadeOutDuration * (1-weight); // 从当前weight处淡出
            }
            else
            {
                SetLookAtEnabled(false);
                _lookAtFadeType = FadeType.None;
            }
        }

        /// <summary>
        /// 设置是否支持空闲时看向玩家
        /// </summary>
        /// <param name="support"></param>
        public void SetSupportLookAtPlayer(bool support)
        {
            _supportLookAtPlayer = support;
        }
        
        /// <summary>
        /// 设置看向的目标
        /// </summary>
        /// <param name="target"></param>
        public void SetLookAtTarget(LookAtType lookAtType, Transform target)
        {
            if (!_lookAtIK)
            {
                return;
            }

            // 检查优先级
            if ((int)lookAtType < (int)_lookAtType)
            {
                return;
            }

            _lookAtType = lookAtType;
            _lookAtHeadWeightLimit = _LookAtHeadWeightLimits[lookAtType];
            _lookAtIK.solver.target = target;
        }

        /// <summary>
        /// 清除LookAt目标，并重置LookAt类型
        /// </summary>
        public void ClearLookAtTarget()
        {
            if (!_lookAtIK)
            {
                return;
            }
            
            _lookAtType = LookAtType.None;
            _lookAtIK.solver.target = null;
        }

        /// <summary>
        /// 获取当前LookAt类型
        /// </summary>
        /// <returns></returns>
        public LookAtType GetLookAtType()
        {
            return _lookAtType;
        }

        /// <summary>
        /// 获取LookAtIK作用的头部骨骼Transform
        /// </summary>
        /// <returns></returns>
        public Transform GetLookAtIKHead()
        {
            if (!_lookAtIK)
            {
                return null;
            }

            return _lookAtIK.solver.head.transform;
        }
        
#endregion

#region 手枪瞄准IK
        /// <summary>
        /// 设置是否开启手枪瞄准IK更新
        /// </summary>
        /// <param name="enabled"></param>
        public void SetHandGunEnabled(bool enabled)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunEnabled = enabled;
        }
        
        /// <summary>
        /// 瞄准IK淡入
        /// </summary>
        public void HandGunAimIKFadeIn()
        {
            if (!_handGunAimIK)
            {
                return;
            }
            _handGunEnabled = true;

            if (_handGunFadeType == FadeType.FadeIn)
            {
                return;
            }
            if (_handGunAimIK.solver.IKPositionWeight >= 1)
            {
                return;
            }

            _handGunFadeType = FadeType.FadeIn;
            float weight = _handGunAimIK.solver.IKPositionWeight;
            weight = weight > 1 ? 1 : weight;
            if (weight > 0)
            {
                _handGunFadeTimer = _handGunFadeInDuration * weight;
            }
            else
            {
                _handGunFadeTimer = 0;
            }
        }
        
        /// <summary>
        /// 瞄准IK淡出
        /// </summary>
        public void HandGunAimIKFadeOut()
        {
            if (!_handGunAimIK)
            {
                return;
            }

            float weight = _handGunAimIK.solver.IKPositionWeight;
            weight = weight > 1 ? 1 : weight;
            if (weight > 0)
            {
                _handGunEnabled = true;
                _handGunFadeType = FadeType.FadeOut;
                _handGunFadeTimer = _handGunFadeOutDuration * (1-weight); // 从当前weight处淡出
            }
            else
            {
                _handGunEnabled = false;
                _handGunFadeType = FadeType.None;
            }
        }


        /// <summary>
        /// 设置瞄准的目标
        /// </summary>
        /// <param name="position"></param>
        public void SetHandGunAimTarget(Transform target)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.target = target;
        }
        /// <summary>
        /// 设置手枪瞄准IK作用的Transform节点
        /// </summary>
        /// <param name="aimTransform"></param>
        public void SetHandGunAimTransform(Transform aimTransform)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.transform = aimTransform;
        }
        /// <summary>
        /// 设置手枪瞄准IK对齐轴
        /// </summary>
        /// <param name="axis"></param>
        public void SetHandGunAimAxis(Vector3 axis)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.axis = axis;
        }
        /// <summary>
        /// 设置手枪瞄准IK的权重
        /// </summary>
        /// <param name="weight"></param>
        public void SetHandGunWeight(float weight)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.IKPositionWeight = weight;
        }

        /// <summary>
        /// 设置手枪瞄准IK的Pole目标
        /// </summary>
        /// <param name="poleTarget"></param>
        public void SetHandGunPoleTarget(Transform poleTarget)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.poleTarget = poleTarget;
        }
        /// <summary>
        /// 设置手枪瞄准IK的Pole目标位置
        /// </summary>
        /// <param name="localPosition"></param>
        public void SetHandGunPoleTargetPosition(Vector3 localPosition)
        {
            if (!_handGunAimIK)
            {
                return;
            }

            if (_handGunPoleTarget)
            {
                _handGunPoleTarget.localPosition = localPosition;
            }
        }
        /// <summary>
        /// 设置手枪瞄准IK的Pole对齐轴
        /// </summary>
        /// <param name="poleAxis"></param>
        public void SetHandGunPoleAxis(Vector3 poleAxis)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.poleAxis = poleAxis;
        }
        /// <summary>
        /// 设置手枪瞄准IK的Pole权重
        /// </summary>
        /// <param name="poleWeight"></param>
        public void SetHandGunPoleWeight(float poleWeight)
        {
            if (!_handGunAimIK)
            {
                return;
            }
            
            _handGunAimIK.solver.poleWeight = poleWeight;
        }

        /// <summary>
        /// 设置手枪瞄准IK刷新后的回调
        /// </summary>
        /// <param name="callback"></param>
        public void SetAfterHandGunIKUpdate(Action callback)
        {
            _afterHandGunIKUpdate = callback;
        }
#endregion

        public void Update()
        {
            if (_aiEntity == null || _aiData == null)
            {
                return;
            }
            // 玩家死亡，禁止刷新IK
            if (!_aiData.isAlive)
            {
                return;
            }
            
            // 检测是否看向玩家
            if (_supportLookAtPlayer && LibertyAIUtils.PlayerController != null)
            {
                Vector3 playerPos = LibertyAIUtils.PlayerController.GetPlayerPosition();
                Vector3 aiPos = _transform.position;
                bool isLookAt = false;
                if (Vector3.SqrMagnitude(aiPos - playerPos) <= _lookAtSqrRadius)
                {
                    Vector3 norVec = _transform.forward;
                    Vector3 temVec = playerPos - aiPos;
                    temVec.y = 0;
                    //xz平面计算角度
                    float angle = Mathf.Acos(Vector3.Dot(norVec, temVec.normalized)) * Mathf.Rad2Deg;
                    isLookAt = angle <= _lookAtAngle * 0.5;
                }

                if (isLookAt)
                {
                    AIEntity playerAIEntity = LibertyAIUtils.PlayerController.playerEntity.AIEntity;
                    if (playerAIEntity)
                    {
                        Transform playerHead = playerAIEntity.viewer.animationAgent.GetLookAtIKHead();
                        if (playerHead)
                        {
                            SetLookAtTarget(LookAtType.LookAtPlayer, playerHead);
                            LookAtIKFadeIn();
                        }
                    }
                }
                else
                {
                    SetLookAtTarget(LookAtType.LookAtPlayer, null);
                    LookAtIKFadeOut();
                }
            }
            
            // LookAt淡入淡出
            if (_lookAtEnabled && _lookAtIK)
            {
                switch (_lookAtFadeType)
                {
                    case FadeType.FadeIn:
                        {
                            // 淡入
                            _lookAtFadeTimer += Time.deltaTime;
                            if (_lookAtFadeTimer >= _lookAtFadeInDuration)
                            {
                                _lookAtIK.solver.IKPositionWeight = 1 * _lookAtHeadWeightLimit;
                                _lookAtFadeType = FadeType.None;
                            }
                            else
                            {
                                _lookAtIK.solver.IKPositionWeight = _lookAtFadeTimer / _lookAtFadeInDuration * _lookAtHeadWeightLimit;
                            }
                        }
                        break;
                    
                    case FadeType.FadeOut:
                        {
                            // 淡出
                            _lookAtFadeTimer += Time.deltaTime;
                            if (_lookAtFadeTimer >= _lookAtFadeOutDuration)
                            {
                                _lookAtIK.solver.IKPositionWeight = 0;
                                _lookAtFadeType = FadeType.None;
                                SetLookAtEnabled(false);
                            }
                            else
                            {
                                _lookAtIK.solver.IKPositionWeight = (1f - _lookAtFadeTimer / _lookAtFadeOutDuration) * _lookAtHeadWeightLimit;
                            }
                        }
                        break;
                }
            }
            // 手枪瞄准淡入淡出
            if (_handGunEnabled && _handGunAimIK)
            {
                switch (_handGunFadeType)
                {
                    case FadeType.FadeIn:
                        {
                            _handGunFadeTimer += Time.deltaTime;
                            if (_handGunFadeTimer >= _handGunFadeInDuration)
                            {
                                _handGunAimIK.solver.IKPositionWeight = 1;
                                _handGunFadeType = FadeType.None;
                            }
                            else
                            {
                                _handGunAimIK.solver.IKPositionWeight = _handGunFadeTimer / _handGunFadeInDuration;
                            }
                        }
                        break;
                    
                    case FadeType.FadeOut:
                        {
                            // 淡出
                            _handGunFadeTimer += Time.deltaTime;
                            if (_handGunFadeTimer >= _handGunFadeOutDuration)
                            {
                                _handGunAimIK.solver.IKPositionWeight = 0;
                                _handGunFadeType = FadeType.None;
                                _handGunEnabled = false;
                            }
                            else
                            {
                                _handGunAimIK.solver.IKPositionWeight = (1f - _handGunFadeTimer / _handGunFadeOutDuration);
                            }
                        }
                        break;
                }
            }
        }

        public void LateUpdate()
        {
            // 玩家死亡，禁止刷新IK
            if (!_aiData.isAlive)
            {
                return;
            }
            
            // 当前质量是否IK
            bool qualityIKSupport;
            if (!_QualityIKSupport.TryGetValue(QualityManager.Inst.CurrentQuality, out qualityIKSupport))
            {
                qualityIKSupport = true;
            }

            if (qualityIKSupport)
            {
                // LookAtIK
                if (_lookAtEnabled && _lookAtIK)
                {
                    _lookAtIK.solver.Update();
                }
                // 手枪瞄准IK
                if (_handGunEnabled && _handGunAimIK && _handGunAimIK.solver.transform)
                {
                    // 瞄准IK距离限制 (处理目标距离过近的bug)
                    if (_handGunAimIK.solver.target && Vector3.Distance(_transform.position, _handGunAimIK.solver.target.position)>=_handGunAimIKLimitRange)
                    {
                        _handGunAimIK.solver.Update();
                    }
                }
            }

            _afterHandGunIKUpdate?.Invoke();
        }
        
    }
}